/*
 * OWLMetadata.java
 * Created on Jul 26, 2004
 *
 */
package abdn.graph.growl;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * OWLMetadata.java
 * @author Rich
 *
 */
public class OWLMetadata
{
  URI baseURI;
  List namespaces = new ArrayList();
  Hashtable uriHash = new Hashtable();  // hash uri strings and prefix strings
  Hashtable prefixHash = new Hashtable();  // hash prefix strings and uri strings
  Hashtable known = new Hashtable();    // hash known prefixes and uri strings
  Hashtable knownURI = new Hashtable();    // hash known uri and prefixes

  public class NameSpace
  {
    String uri;
    String prefix;
    boolean imported;

    NameSpace(String u, String pre, boolean imp)
    {
      uri = u;
      prefix = pre;
      imported = imp;
    }

    /**
     * Method isImported
     * @return whether it has imports
     */
    public boolean isImported()
    {
      return imported;
    }

    /**
     * Method getPrefix
     * @return the prefix
     */
    public String getPrefix()
    {
      return prefix;
    }

    /**
     * Method getUri
     * @return the URI
     */
    public String getUri()
    {
      return uri;
    }

    /**
     * Method setImported
     * @param b whether the ontology has import or not
     */
    public void setImported(boolean b)
    {
      imported = b;
    }

    /**
     * Method setPrefix
     * @param string
     */
    public void setPrefix(String string)
    {
      prefix = string;
    }

    /**
     * Method setUri
     * @param uri
     */
    public void setUri(String uri)
    {
      this.uri = uri;
    }

  }

  public OWLMetadata()
  {
    addKnown("xsd", "http://www.w3.org/2001/XMLSchema#");
  }

  private void addKnown(String prefix, String uri)
  {
    known.put(prefix, uri);
    knownURI.put(uri, prefix);
  }

  /**
   * Method getBaseURI
   * @return URI
   */
  public URI getBaseURI()
  {
    return baseURI;
  }

  /**
   * Method setBaseURI
   * @param uri being the namespace
   */
  public void setBaseURI(URI uri)
  {
    String s;
    if( baseURI != null )
    {
      s = baseURI.toString() + "#";
      prefixHash.remove(getPrefixOfURI(s));
      uriHash.remove(s);
    }
    baseURI = uri;
    s = uri.toString() + "#";
    uriHash.put(s, "");
    prefixHash.put("", s);
  }

  public void addNamespace(String uri, String prefix, boolean imported)
  {
//TODO check it's not already there
    if( !uriHash.containsKey(uri) )
    {
      uriHash.put(uri, prefix);
    }
    if( !prefixHash.containsKey(prefix) )
    {
      prefixHash.put(prefix, uri);
    }
    namespaces.add(new NameSpace(uri, prefix, imported));
  }

  public void changeNamespace(int index, String uri, String prefix)
  {
    NameSpace ns = (NameSpace)namespaces.get(index);
    prefixHash.remove(getPrefixOfURI(uri));
    uriHash.remove(uri);
//TODO  check it's not already there
    if( !uriHash.containsKey(uri) )
    {
      uriHash.put(uri, prefix);
    }
    prefixHash.put(prefix, uri);
    ns.setUri(uri);
    ns.setPrefix(prefix);
  }

  public void deleteNamespace(int index)
  {
    NameSpace ns = (NameSpace)namespaces.get(index);
    String s = ns.getUri();
    String p = getPrefixOfURI(s);
    uriHash.remove(s);
    prefixHash.remove(p);
    namespaces.remove(index);
  }

  List getNamespaces()
  {
    return namespaces;
  }

  /**
   * Method getURIOfPrefix
   * If the prefix is known, return the corresponding uri.
   * Otherwise return the string that was passed in.
   * @param prefix
   * @return the URI prefix
   */
  public String getURIOfPrefix(String prefix)
  {
    String uri;
    if( prefix == null )
    {
      prefix = "";
    }
    uri = (String)prefixHash.get(prefix);
    if( uri == null )
    {
      uri = (String)known.get(prefix);
    }
    return uri == null ? prefix : uri;
  }

  private String getURIFromPrefixHash(String prefix)
  {
    return (String)prefixHash.get(prefix);
  }

  public String getPrefixOfFullURI(URI uri)
	{
    String ssp = getURISSP(uri);
	  String prefix = (String)uriHash.get(ssp);
    if(prefix == null)
    {
      if( (prefix = (String)knownURI.get(ssp)) == null )
      {
        prefix = ssp;
      }
    }
    return prefix;
	}

	public String getNamespacePrefix(URI uri){
		String pp= getPrefixOfFullURI(uri);
		if(pp.equalsIgnoreCase(""))
		  return pp;
		else return pp+":";
	}

  public String getPrefixOfURI(String uri)
  {
    return (String)uriHash.get(uri);
  }

  private String getURISSP(URI uri)
  {
    String ssp = null;
    try {
      if (uri.getFragment() != null) {
      /* It's of the form http://xyz/path#frag */
        ssp =
          new URI(uri.getScheme(), uri.getSchemeSpecificPart(), null)
            .toString();
      }
    }
    catch (URISyntaxException ex) {
    }
    if(ssp == null)
    {
      ssp = uri.toString();
    }
    if( !ssp.endsWith("#"))
    {
      ssp = ssp + "#";
    }
    return ssp;
  }

  public String shortForm(URI uri) {
    if (uri == null) {
      return "_";
    }
    try {
      if (uri.getFragment() == null) {
        /* It's not of the form http://xyz/path#frag */
        return uri.toString();
      }
      /* It's of the form http://xyz/path#frag */
      String ssp =
        new URI(uri.getScheme(), uri.getSchemeSpecificPart(), null)
          .toString();
      if( !ssp.endsWith("#"))
      {
        ssp = ssp + "#";
      }
      if( knownURI.contains(ssp) )   // common schemas that are displayed without a prefix
      {
        return uri.getFragment();
      }
      String prefix = getPrefixOfURI(ssp);
      if( prefix == null )
        return uri.toString();
      else if( prefix.length() == 0 )
        return uri.getFragment();
      else
        return prefix + ":" + uri.getFragment();
    }
    catch (URISyntaxException ex) {
    }
    return uri.toString();
  }

  public URI uriFromShortForm(String s)
  {
    StringBuffer sb = new StringBuffer();
    String[] parts = s.split(":", 2);
    if(parts.length == 2)
    {
      sb.append(getURIOfPrefix(parts[0]));
      sb.append(parts[1]);
      s = sb.toString();
    }
    else
    {
      sb.append(baseURI.toString());
      sb.append("#");
      sb.append(parts[0]);
      s = sb.toString();
    }
    try
    {
      return new URI(s);
    }
    catch (URISyntaxException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return null;
  }

  public String fragmentFromShortForm(String s)
  {
    String[] parts = s.split(":", 2);
    if(parts.length == 2)
    {
      return parts[1];
    }
    return s;
  }

  public void setDefaults()
  {
    namespaces.clear();
    try
    {
      setBaseURI(new URI("http://a.com/ontology"));
      addNamespace("http://www.w3.org/2002/07/owl#", "owl", false);
      addNamespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf", false);
      addNamespace("http://www.w3.org/2000/01/rdf-schema#", "rdfs", false);
    }
    catch (URISyntaxException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  public String getTypeShortForm(String name)
  {
    if( name.equalsIgnoreCase("Literal") )
      return "rdfs:" + name;
    return "xsd:" + name;
  }
}
